# Dataframe bilden aus zwei Vektorenparteinamen <-data.frame(kuerzel =c("fdp", "sps", "svp", "mitte", "evp", "gps", "glp", "ucsp", "pda", "sd", "edu", "fps", "lega", "kvp", "mcg", "cvp", "bdp", "lps", "ldu", "poch", "rep", "eco", "sgv", "sbv", "sgb", "travs", "sav", "vsa", "vpod", "voev", "tcs", "vcs", "acs", "sbk", "ssv", "gem", "kdk", "kkjpd", "gdk", "ldk"),name =c("Freisinnig-demokratische Partei (FDP.Die Liberalen)", "Sozialdemokratische Partei", "Schweizerische Volkspartei (bis 1936 Parolen der BGB Bern)", "Die Mitte", "Evangelische Volkspartei", "Grüne Partei der Schweiz", "Grünliberale Partei", "Christlichsoziale Partei der Schweiz (von der CVP unabhängige CSP)", "Partei der Arbeit", "Schweizer Demokraten", "Eidgenössisch-Demokratische Union", "Autopartei", "Lega dei Ticinesi", "Katholische Volkspartei", "Mouvement Citoyens Genevois", "Christlichdemokratische Volkspartei", "Bürgerlich-Demokratische Partei", "Liberale Partei der Schweiz", "Landesring der Unabhängigen", "Progressive Organisationen der Schweiz", "Schweizerische Republikanische Bewegung", "Economiesuisse (bis 15.9.2000: Schweizerischer Handels- und Industrieverein SHIV (Vorort))", "Schweizerischer Gewerbeverband", "Schweizer Bauernverband", "Schweizerischer Gewerkschaftsbund", "Travail.Suisse (bis 2002: Parolen des Christlichnationalen Gewerkschaftsbunds (CNG); dieser fusionierte per 1.1.2003 mit der VSA zu Travail.Suisse)", "Schweizerischer Arbeitgeberverband (bis 1996: Zentralverband Schweizerischer Arbeitgeber-Organisationen ZSAO)", "Vereinigung schweizerischer Angestelltenverbände", "Verband des Personals öffentlicher Dienste", "Verband öffentlicher Verkehr", "Touring Club Schweiz", "Verkehrs-Club der Schweiz", "Automobil Club der Schweiz", "Schweizer Bischofskonferenz", "Schweizerischer Städteverband", "Schweizerischer Gemeindeverband", "Konferenz der Kantonsregierungen", "Konferenz der kantonalen Justiz- und Polizeidirektoren", "Schweizerische Gesundheitsdirektorenkonferenz", "Konferenz der kantonalen Landwirtschaftsdirektoren"),stringsAsFactors =FALSE)# Neue Spalte mit "p-" Präfix für späteren Lookup der Parteiparolenparteinamen$p_kuerzel <-paste0("p-", parteinamen$kuerzel) # Parteikürzel in Grossbuchstaben parteinamen$kuerzel <-toupper(parteinamen$kuerzel)# Spaltenreihenfolge anpassen: p_kuerzel, kuerzel, nameparteinamen <- parteinamen[, c("p_kuerzel", "kuerzel", "name")]# Anzeige mit datatable()datatable(parteinamen,filter ='top',options =list(pageLength =7,search =list(regex =TRUE,caseInsensitive =TRUE)))
2.2 Abstimmungen
Code anzeigen
# Schweizweite Abstimmungenvoting_raw <-read_delim("~/CAS/Zertifikatsarbeit/data/votes/abstimmungen_swissvotes_DATASET CSV 09-02-2025.csv",delim =";",escape_double =FALSE,trim_ws =TRUE,show_col_types =FALSE)# TODO evt. nur random sample berechnen auf grund Grösse...datatable(voting_raw,filter ='top',options =list(pageLength =7,search =list(regex =TRUE,caseInsensitive =TRUE)))
tibble [155 × 21] (S3: tbl_df/tbl/data.frame)
$ Active : logi [1:155] TRUE FALSE TRUE FALSE FALSE FALSE ...
$ FirstName : chr [1:155] "Marianne" "Marianne" "Pirmin" "Pirmin" ...
$ LastName : chr [1:155] "Binder-Keller" "Binder-Keller" "Bischof" "Bischof" ...
$ GenderAsString : chr [1:155] "f" "f" "m" "m" ...
$ CantonName : chr [1:155] "Aargau" "Aargau" "Solothurn" "Solothurn" ...
$ CantonAbbreviation : chr [1:155] "AG" "AG" "SO" "SO" ...
$ CouncilName : chr [1:155] "Ständerat" "Nationalrat" "Ständerat" "Nationalrat" ...
$ ParlGroupName : chr [1:155] "Die Mitte-Fraktion. Die Mitte. EVP." "Die Mitte-Fraktion. Die Mitte. EVP." "Die Mitte-Fraktion. Die Mitte. EVP." "Fraktion CVP/EVP/glp" ...
$ ParlGroupAbbreviation: chr [1:155] "M-E" "M-E" "M-E" "M-E" ...
$ PartyName : chr [1:155] "Die Mitte" "Christlichdemokratische Volkspartei der Schweiz" "Die Mitte" "Christlichdemokratische Volkspartei der Schweiz" ...
$ PartyAbbreviation : chr [1:155] "M-E" "CVP" "M-E" "CVP" ...
$ MaritalStatusText : chr [1:155] "verheiratet" "verheiratet" NA NA ...
$ Nationality : chr [1:155] "Schweiz" "Schweiz" "Schweiz" "Schweiz" ...
$ BirthPlace_City : chr [1:155] "Zürich" "Zürich" "Solothurn" "Solothurn" ...
$ BirthPlace_Canton : chr [1:155] "Zürich" "Zürich" "Solothurn" "Solothurn" ...
$ Mandates : chr [1:155] "Mitglied Präsidium Die Mitte Schweiz; Präsidentin Die Mitte Aargau" "Mitglied Präsidium Die Mitte Schweiz; Präsidentin Die Mitte Aargau" "Legislative des Kantons (Kantonsrat): von April 2005 bis November 2007; Exekutive der Gemeinde (Gemeinderat) So"| __truncated__ "Legislative des Kantons (Kantonsrat): von April 2005 bis November 2007; Exekutive der Gemeinde (Gemeinderat) So"| __truncated__ ...
$ DateJoining : chr [1:155] "04.12.2023" "02.12.2019" "04.12.2023" "03.12.2007" ...
$ DateLeaving : chr [1:155] NA "03.12.2023" NA "04.12.2011" ...
$ Citizenship : chr [1:155] "Baden (AG),Untersiggenthal (AG),Zurzach (Bad Zurzach) (AG)" "Baden (AG),Untersiggenthal (AG),Zurzach (Bad Zurzach) (AG)" "Eggersriet (SG),Grub (AR)" "Eggersriet (SG),Grub (AR)" ...
$ DateOfBirth : chr [1:155] "15.06.1958" "15.06.1958" "24.02.1959" "24.02.1959" ...
$ DateOfDeath : logi [1:155] NA NA NA NA NA NA ...
2.3.2 Kantonsebene
2.3.2.1 Kantonale Parlamente (Legislative)
Code anzeigen
# TODO Die Kantonalen Abstimmungen finden nicht in allen kantonen gleichzeitg statt. Deshalb genauer die Räte/Konstellation zum Zeitpunkt der jeweiligen Abstimmung zu prüfen.# Struktur der "schön formatierten" Exceldatei lässt keinen "simplen" Import zu.# Header ist in Zeile 2 und nicht vollständig# Daten (für Kantone) starten in Zeile 4 aber enden auf Zeile 29 bevor es mit Kommentaren und Fussnoten weitergeht # Header aus Zeile 2 für Spaltennamen lesentmp_header <-read_excel("~/CAS/Zertifikatsarbeit/data/elections/je-d-17.02.05.01.03_KANTON_Kantonale_Parlamentswahlen.xlsx", sheet =1, skip =1, # Header ist Zeile 2n_max =0) %>%names()# Lücken im Header anpassen (i.e. erste beiden Spalten benennen)tmp_header <-c("Kanton", "Leer", tmp_header)tmp_name_map <-c("Kanton"="Kanton","Leer"="Leer","Wahljahr 5)"="Wahljahr","FDP 2)"="FDP","SP"="SP","SVP"="SVP","LPS 2)"="LPS","EVP"="EVP","CSP"="CSP","GLP"="GLP","Die Mitte 8)"="Mitte","CVP 3) 8)"="CVP","BDP 8)"="BDP","PdA"="PdA","PSA"="PSA","Grüne 9)"="Grüne","FGA"="FGA","Sol."="Sol.","EDU"="EDU","Lega"="Lega","MCG (MCR)"="MCR","Übrige 4)"="Übrige","Total"="Total")# Automatisch ersetzentmp_header <-ifelse(tmp_header %in%names(tmp_name_map), tmp_name_map[tmp_header], tmp_header)print(tmp_header)
# Daten ab Zeile 4 importierenelec_kantonsparlament_raw <-read_excel("~/CAS/Zertifikatsarbeit/data/elections/je-d-17.02.05.01.03_KANTON_Kantonale_Parlamentswahlen.xlsx", sheet =1, skip =3, # überspringt die ersten 3 Zeilencol_names = tmp_header)# Schritt 4: Nur Zeilen behalten, in denen "Wahljahr" nicht NA istelec_kantonsparlament <- elec_kantonsparlament_raw %>%filter(!is.na(Wahljahr)) %>%select(-Leer)# Ergebnis anzeigenprint(elec_kantonsparlament)
# TODO Die Kantonalen Abstimmungen finden nicht in allen kantonen gleichzeitg statt. Deshalb genauer die Räte/Konstellation zum Zeitpunkt der jeweiligen Abstimmung zu prüfen.# Struktur der "schön formatierten" Exceldatei lässt keinen "simplen" Import zu.# Header ist in Zeile 2 und nicht vollständig# Daten (für Kantone) starten in Zeile 4 aber enden auf Zeile 29 bevor es mit Kommentaren und Fussnoten weitergeht # Header aus Zeile 2 für Spaltennamen lesentmp_header <-read_excel("~/CAS/Zertifikatsarbeit/data/elections/je-d-17.02.06.01_KANTON_Kantonale_Regierungswahlen.xlsx", sheet =1, skip =1, # Header ist Zeile 2n_max =0) %>%names()# Lücken im Header anpassen (i.e. erste beiden Spalten benennen)tmp_header <-c("Kanton", tmp_header)tmp_name_map <-c("Kanton"="Kanton","Wahljahr 1"="Wahljahr","FDP 2"="FDP","SP"="SP","SVP"="SVP","LP 2"="LPS","EVP"="EVP","CSP"="CSP","GLP"="GLP","Die Mitte 3"="Mitte","CVP 3"="CVP","BDP 3"="BDP","PdA"="PdA","PSA"="PSA","Grüne 5"="Grüne","FGA"="FGA","Sol."="Sol.","Lega"="Lega","MCG (MCR)"="MCR","Übrige 4"="Übrige","Total"="Total")# Automatisch ersetzentmp_header <-ifelse(tmp_header %in%names(tmp_name_map), tmp_name_map[tmp_header], tmp_header)print(tmp_header)
# Daten ab Zeile 4 importierenelec_kantonsregierung_raw <-read_excel("~/CAS/Zertifikatsarbeit/data/elections/je-d-17.02.06.01_KANTON_Kantonale_Regierungswahlen.xlsx", sheet =1, skip =3, # überspringt die ersten 3 Zeilencol_names = tmp_header)# Schritt 4: Nur Zeilen behalten, in denen "Wahljahr" nicht NA istelec_kantonsregierung <- elec_kantonsregierung_raw %>%filter(!is.na(Wahljahr)) # Ergebnis anzeigenprint(elec_kantonsparlament)
voting <- voting_raw %>%mutate(datum =as.Date(datum, format ="%d.%m.%Y")) %>%# Format-Umwandlungfilter(datum >=as.Date("2019-12-31")) %>%# Vergleichselect(anr, # Spalten-Wahl datum, titel_kurz_d, titel_off_d, rechtsform, #1 Obligatorisches Referendum#2 Fakultatives Referendum#3 Volksinitiative#4 Direkter Gegenentwurf zu einer Volksinitiative#5 Stichfrage dep,`br-pos`, #1 Befürwortend#2 Ablehnend#3 Keine#8 Vorzug für den Gegenentwurf (bei Stichfragen)#9 Vorzug für die Volksinitiative (bei Stichfragen)#. Missing legisjahr,`pa-iv`,`bv-pos`, #1 Befürwortend#2 Ablehnend#3 Keine Abstimmungsempfehlung des Parlaments#8 Vorzug für den Gegenentwurf (bei Stichfragen)`nr-pos`, #1 Befürwortende Mehrheit im Nationalrat#2 Ablehnende Mehrheit im Nationalrat#3 Keine Abstimmungsempfehlung des Nationalrats#8 Vorzug für den Gegenentwurf (bei Stichfragen) nrja, nrnein,`sr-pos`, #1 Befürwortende Mehrheit im Ständerat#2 Ablehnende Mehrheit im Ständerat#3 Keine Abstimmungsempfehlung des Ständerats#8 Vorzug für den Gegenentwurf (bei Stichfragen) srja, srnein,starts_with("p-"),#1 Ja-Parole#2 Nein-Parole#3 keine Parole abzugeben#4 empfahl, einen leeren Stimmzettel einzulegen#5 Stimmfreigabe#8 Bevorzugung des Gegenentwurfs (bei Stichfrage)#9 Bevorzugung der Volksinitiative (bei Stichfrage)#66 Neutral: keine Parole oder Empfehlung auf leer einlegen #9999 Organisation existiert nicht#. Unbekannt volk, #0 Eine Mehrheit der Abstimmenden hat die Vorlage abgelehnt#1 Eine Mehrheit der Abstimmenden hat die Vorlage angenommen#8 Bei Stichfragen: Mehrheit für Gegenentwurfs#9 Bei Stichfragen: Mehrheit Volksinitiative stand,#0 Die Vorlage hat keine Mehrheit der Standesstimmen er-reicht#1 Die Vorlage hat die Mehrheit der Standesstimmen erreicht#3 Ständemehr nicht notwendig#8 Bei Stichfragen: Mehrheit für Gegenentwurf#9 Bei Stichfragen: Mehrheit für Volksinitiative annahme, #0 Ablehnung der Vorlage#1 Annahme der Vorlage#8 Bei Stichfragen: Gegenentwurf angenommen#9 Bei Stichfragen: Volksinitiative angenommen#. Bei Stichfragen: Ergebnis der Stichfrage obsolet berecht, stimmen, bet, leer, ungultig, gultig, volkja, volknein,`volkja-proz` )
#TODO Es kann innerhalb der Legislatur Wechsel geben --> Anstelle der heute "Aktiven" ist es deshalb genauer die Räte/Konstellation zum Zeitpunkt der jeweiligen Abstimmung zu prüfen. # Anzeige mit datatable()datatable(elec_nationalrat,filter ='top',options =list(pageLength =7,search =list(regex =TRUE,caseInsensitive =TRUE)))
Code anzeigen
# Fehlende Werte (NA), Klassen und Levels prüfenAbstract(elec_nationalrat)
# Sitze pro Kanton, Partei und Jahr # long format df_sum <- elec_nationalrat_reduced %>%group_by(CantonAbbreviation, PartyAbbreviation) %>%summarise(sum_value =sum(value, na.rm =TRUE),.groups ="drop")# wide format# Pivotieren: Partei-Spalten erzeugen df_wide <- df_sum %>%pivot_wider(names_from = PartyAbbreviation,values_from = sum_value,values_fill =0)# Partei-Spaltennamen extrahieren (ohne Kanton/Jahr) partei_cols <-setdiff(names(df_wide),c("CantonAbbreviation"))# Spaltensummen der Parteien berechnen für Sortierung partei_sums <-colSums(df_wide[partei_cols])# Zeilensumme der Kantone/Jahre hinzufügen df_wide$Total <-rowSums(df_wide[partei_cols])# Parteispalten-Anordnung nach Summe sortieren sorted_partei <-names(sort(partei_sums,decreasing =TRUE))# Dataframe neu anordnen: Kanton/Jahr, sortierte und gefilterte Parteien elec_nationalrat_final <- df_wide[, c(setdiff(names(df_wide), partei_cols), sorted_partei)] %>%arrange(desc(Total))datatable(elec_nationalrat_final,filter ='top',options =list(pageLength =7,search =list(regex =TRUE,caseInsensitive =TRUE)))
3.2.1.2 Ständerat
Code anzeigen
#TODO Es kann innerhalb der Legislatur Wechsel geben --> Anstelle der heute "Aktiven" ist es deshalb genauer die Räte/Konstellation zum Zeitpunkt der jeweiligen Abstimmung zu prüfen.# Anzeige mit datatable()datatable(elec_ständerat,filter ='top',options =list(pageLength =7,search =list(regex =TRUE,caseInsensitive =TRUE)))
Code anzeigen
# Fehlende Werte (NA), Klassen und Levels prüfenAbstract(elec_ständerat)
# Sitze pro Kanton, Partei und Jahr # long format df_sum <- elec_ständerat_reduced %>%group_by(CantonAbbreviation, PartyAbbreviation) %>%summarise(sum_value =sum(value, na.rm =TRUE),.groups ="drop")# wide format# Pivotieren: Partei-Spalten erzeugen df_wide <- df_sum %>%pivot_wider(names_from = PartyAbbreviation,values_from = sum_value,values_fill =0)# Partei-Spaltennamen extrahieren (ohne Kanton/Jahr) partei_cols <-setdiff(names(df_wide),c("CantonAbbreviation"))# Spaltensummen der Parteien berechnen für Sortierung partei_sums <-colSums(df_wide[partei_cols])# Zeilensumme der Kantone/Jahre hinzufügen df_wide$Total <-rowSums(df_wide[partei_cols])# Parteispalten-Anordnung nach Summe sortieren sorted_partei <-names(sort(partei_sums,decreasing =TRUE))# Dataframe neu anordnen: Kanton/Jahr, sortierte und gefilterte Parteien elec_ständerat_final <- df_wide[, c(setdiff(names(df_wide), partei_cols), sorted_partei)] %>%arrange(desc(Total))datatable(elec_ständerat_final,filter ='top',options =list(pageLength =7,search =list(regex =TRUE,caseInsensitive =TRUE)))
3.2.2 Kantonsebene
3.2.2.1 Kantonsparlament
3.2.2.2 Kantonsregierung
3.3 Parteilandschaft
3.3.1 Multi-Dimensions-Model
3.3.1.1 Minimalwerte
Für jede Partei den Minimalwert des Abstimmungsverhaltens zu verwenden, basiert auf der Zielsetzung, die klarste politische Position einer Partei in einem bestimmten Themenbereich zu identifizieren. Diese Methodik stellt sicher, dass auch bei wenigen Abweichungen von der Mehrheitslinie die tatsächliche Haltung der Partei deutlich erkennbar bleibt.
3.3.1.4 Hauptparteien: Durchschnittswerte als Zentrum und Min/Max als Ellipse / Verbände sowie Klein- und Regionalparteien nur mit ihrem Durchschnittswert